package com.linkoog.devtools.utils;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;

import java.util.List;

public class PsiMethodUtil {

    /**
     *   查找PsiMethod
     */
    public static PsiMethod findPsiMethod(Project project, String fileUrl, int psiElementOffset){
        if (project == null || fileUrl == null) return null;

        VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(fileUrl);
        if (virtualFile == null) return null;

        PsiFile psiFile = PsiUtil.getPsiFile(project, virtualFile);
        PsiElement psiElement = psiFile.findElementAt(psiElementOffset);
        return PsiTreeUtil.getParentOfType(psiElement, PsiMethod.class);
    }

    /**
     *  是否为object上的方法
     */
    public static boolean isObjectMethod(PsiMethod psiMethod){
        final PsiFile psiFile = psiMethod.getContainingFile();
        if (psiFile == null) return false;

        return "Object.class".equals(psiFile.getName()) ;
    }

    /**
     *   解析PsiMethod的PsiAnnotation 注解
     */
    public static PsiAnnotation parseMethodAnnotation(PsiMethod psiMethod, List<String> methodAnnotationList, boolean findSuper) {
        if (psiMethod == null || methodAnnotationList == null || methodAnnotationList.isEmpty()){
            return null;
        }

        PsiAnnotation psiAnnotation = doParseMethodAnnotation(psiMethod, methodAnnotationList);
        if (psiAnnotation != null) {
            return psiAnnotation;
        }

        if (findSuper){
            PsiMethod[] superPsiMethods = psiMethod.findSuperMethods(true);
            for (PsiMethod superPsiMethod : superPsiMethods) {
                PsiAnnotation annotation = doParseMethodAnnotation(superPsiMethod, methodAnnotationList);
                if (annotation != null) {
                    return annotation;
                }
            }
        }

        return null;
    }

    private static PsiAnnotation doParseMethodAnnotation(PsiMethod psiMethod, List<String> methodAnnotationList) {
        for (String methodAnnotationQualifiedName : methodAnnotationList) {
            PsiAnnotation psiAnnotation = psiMethod.getAnnotation(methodAnnotationQualifiedName);
            if (psiAnnotation != null){
                return psiAnnotation;
            }
        }
        return null;
    }
}
